iT邦幫忙

2023 iThome 鐵人賽

DAY 28
0

已經到了鐵人賽最後二天了,今天的主題方向和之前會有一些不太相同,要和大家說明在OpenStack網路裡,Trunk的功能是如何實現的。先來看一下官方文件對於Trunk的定義吧。

The network trunk service allows multiple networks to be connected to an instance using a single virtual NIC (vNIC). Multiple networks can be presented to an instance by connecting it to a single port.

對照之前的介紹,當VM連至一個Network時,Network上會有一個Port,這個Port的attached device是comppute: nova,在VM就可以看到一張NIC連到這一個Port;如果VM要連至多個Network時,VM裡會有多個NIC,每個NIC都是連到OpenStack上的某一個Port. 這會衍生二個明顯的問題:

  1. 如果VM要連到上千個Network時,在VM裡就會有到上千個NIC;
  2. 一旦有VM連到一個Port上,VM上就會出現一個相對應的NIC, 無法隨意管理NIC。

為了達成單獨使用一個NIC,完成讓VM自行管理連到那幾個Network上,就引用了VLAN Trunk的想法,在VM的一個NIC上(eg. eth0),可以配置多個VLAN ID(eg. eth0.100, eth.200...),每個VLAN對應至不同的Network。VM本身可以透過設定sub interface,自行決定要和那些Network相連。

Neutron Trunking是讓VM可以自行動態的設定要與那幾個Network相連,但在OpenStack上,仍然要事先建立Network與Port。所以對照二種模式,Port的數量與Netwrok數量是相同的。但VM只有一個NIC,可以依照需求,建立sub interface。

Legancy Trunk
gh gh

如何解決由VM instance送出的帶有VLAN tag的封包

因為Neutron Trunking是使用 VLAN 的概念來達到讓一個VM使用一個NIC連接到多個Network,由圖可以看到,會有不同VLAN的封包在VM的NIC上傳送。致於要如何讓VM上帶有VLAN tag的封包如何透過實體網路,送到不同實體主機上的VM上,在OpenStack 社群裡提出二個方案:

  1. Neutron VLAN Transparency: 因為不同的VLAN要在一個NIC上傳送,表示這個VM的行為就如何VLAN的trunk port。通常VM所連接到的vSwitch與實體switch都要啟用trunk port,才能夠正確的傳送帶有VLAN tag的封包,這使使用Trunk會受限於實體網路的架構。
  2. Neutron VLAN aware VMs: 為了解決VLAN Transparency 需要switch啟用trunk port的要求,現在通常用此方案來實現trunk。

建立Neutron Trunking

如果要讓VM能使用Trunk,和VM相關的網路設定有很大的不同,我們來看一下整個過程要做那些變動:

  1. 建立 OpenStack Network,1個Network做為parent network,其他則做為child network。一般來說,child network的數量,就是VM預計會使用的VLAN數量,也就是說,一個child network,可以看成是一個VLAN。
openstack network create  parent
openstack network create  child1

特別注意這邊建立Network時,network type不必選VLAN,OVN會透過logical flow,去模擬出好像有VLAN 的封包的行為。

  1. 為每個Network(包括parent與child network)都建立subnet。
openstack subnet create --network parent --subnet-range 10.0.11.0/24 parent_subnet
openstack subnet create --network child1 --subnet-range 10.0.22.0/24 child1_subnet
  1. 在每個Network上都建立Port。在之前的介紹中,建立VM時,直接指定Network,OpenStack會直接幫我們在Network上建立Port,但是要使用Trunk,我們必需手動建立Port。
openstack port create --network parent parent0
parent_mac="$( openstack port show parent0 | awk '/ mac_address / { print $4 }' )"

openstack port create --network child1 --mac-address "$parent_mac" child1

在建立child port時,我們手動指定child port和parent port有相同的MAC addrsss。這是因為在稍後,我們會在VM裡建立綁在eth0上的sub interface,Linux的行為是sub interface的MAC addr會和原本的interface相同。因為instance 的eth0的MAC addr是由parent port決定的,所以,建child port時,指定child port的MAC和parent port相同。如此一來,child port、parent port、eth0、eth0.XXX的MAC都會完全相同

  1. 建立trunk。建立trunk時,一定要指定一個parent port。之後再把child port加入trunk。
openstack network trunk create --parent-port parent0 trunk0
openstack network trunk set --subport port=child1,segmentation-type=vlan,segmentation-id=100 trunk0
  1. 建立VM時, 使用parent port
IMAGE_ID=$(openstack image show cirros --format json | jq -r .id)
parent_port_id=`openstack port list --name parent0 -f value -c ID`

openstack server create --nic port-id=${parent_port_id} --flavor m1.nano --image $IMAGE_ID vm_1
  1. 在VM 內建立sub interface
ip link add link eth0 name eth0.200 type vlan id 100
ip link set eth0.100 up
  1. 為了驗證VM間的連通性,建立一個新的Trunk,但是使用相同的parent network與child network,再建立一個vm使用新trunk
  • 建新trunk
    penstack port create --network parent parenta
    arent_mac="$( openstack port show parenta | awk '/ mac_address / { print $4 }' )"
    penstack port create --network child1 --mac-address "$parent_mac" childb
    
    
    penstack network trunk create --parent-port parenta --subport port=childb,segmentation-type=vlan,segmentation-id=100 trunk1
    arent_port_id=`openstack port list --name parenta -f value -c ID`
    penstack server create --nic port-id=${parent_port_id} --flavor m1.nano --image $IMAGE_ID vm_2
    ``
    
  • 在新instance裡啟用sub interface
    p link add link eth0 name eth0.100 type vlan id 100
    p link set eth0.100 up
    ``
    
    

OpenStack 網路架構

查看OpenStack上Network 、Trunk、Port的資訊,確實與圖中預期要建立的長像是相同的

gh

  1. 有二個Geneve Network
# Network
openstack network  list --long -c ID -c "Network Type" | abbrev

+--------+--------------+
| ID     | Network Type |
+--------+--------------+
| 624780 | geneve       |
| 91a36d | geneve       |
+--------+--------------+
  1. 有二個VM,且都只有用到parent network 上的port
# Server
openstack serve list --long -c Name -c Networks | abbrev

+------+-------------------+
| Name | Networks          |
+------+-------------------+
| vm_2 | parent=10.0.11.21 |
| vm_1 | parent=10.0.11.4  |
+------+-------------------+
  1. 有二個trunk,各別使用不同的左手邊parent network上的不同port做為parent port
# Trunk
openstack network trunk list

+--------+--------+-------------+-------------+
| ID     | Name   | Parent Port | Description |
+--------+--------+-------------+-------------+
| 1c5b0a | trunk0 | 0fd168      |             |
| cacf0e | trunk1 | e21fe6      |             |
+--------+--------+-------------+-------------+
  1. 共有6個Port,同一個trunk的parent port 和child port 會有相同的MACC
# Port
openstack port  list --long -c ID -c "MAC Address"  -c "Fixed IP Addresses" -c "Device Owner" | abbrev
+--------+-------------------+----------------------------------------------+---------------------+
| ID     | MAC Address       | Fixed IP Addresses                           | Device Owner        |
+--------+-------------------+----------------------------------------------+---------------------+
| 424bc4 | fa:16:3e:d6:85:ec | ip_address='10.0.22.2', subnet_id='03ec93'   | network:distributed |
| c49d3b | fa:16:3e:68:61:12 | ip_address='10.0.11.2', subnet_id='e39d80'   | network:distributed |
| 70789a | fa:16:3e:d5:3c:74 | ip_address='10.0.22.187', subnet_id='03ec93' | trunk:subport       |
| e21fe6 | fa:16:3e:d5:3c:74 | ip_address='10.0.11.21', subnet_id='e39d80'  | compute:nova        |
| 0fd168 | fa:16:3e:47:ae:23 | ip_address='10.0.11.4', subnet_id='e39d80'   | compute:nova        |
| 7c5a44 | fa:16:3e:47:ae:23 | ip_address='10.0.22.225', subnet_id='03ec93' | trunk:subport       |
+--------+-------------------+----------------------------------------------+---------------------+ 

OpenStack 與OVN 元件關係

gh

我們來看一下在OVN上,有那些logical switch被建立出來。因為在OpenStack上有二個Geneve Network,所以可以看到有二個logical switch。這二個switch分別連到VM上的二個不同的NIC。唯一的不同點,在於做為child network的logical switch上,logical switch port上,可以看到tag的屬性,表示通過這個port的封包都會帶有VLAN tag,而在VM上,就會連到相對應的VLAN NIC。如果二個VM是透過parent network網段溝通的話,會使用左邊的logical switch;反之,如果是用child network網段溝通的話,會使用右邊的switch。

ovn-nbctl show | abbrev

switch 6738bc (neutron-91a36d) (aka child1)
    port 5aee74 (aka child1)
        parent: 7fb5cc
        tag: 100
        addresses: ["fa:16:3e:47:ae:23 10.0.22.225"]
    port 30ed0e
        type: localport
        addresses: ["fa:16:3e:d6:85:ec 10.0.22.2"]
    port 70789a (aka childb)
        parent: 7ad541
        tag: 100
        addresses: ["fa:16:3e:d5:3c:74 10.0.22.187"]
switch bafb8c (neutron-f32d30) (aka parent)
    port 7ad541 (aka parenta)
        addresses: ["fa:16:3e:d5:3c:74 10.0.11.21"]
    port 051a81
        type: localport
        addresses: ["fa:16:3e:68:61:12 10.0.11.2"]
    port 7fb5cc (aka parent0)
        addresses: ["fa:16:3e:47:ae:23 10.0.11.4"]

Reference

  1. VLAN trunking support in Neutron
  2. VLAN Trunk in OpenStack Neutron and SDN
  3. Trunk ports in OVN
  4. Neutron/TrunkPort Wiki
  5. VLAN Trunk在OpenStack Neutron及SDN中的实现
  6. openstack如何支持vlan trunk功能

上一篇
Day-27: Distributed Floating IP
下一篇
Day-29: Trunking的連通性
系列文
在OpenStack Neutron的ovn-networking裡挖呀挖呀挖30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言